package com.rtf.framework.web.mvc.rest.curd;

import com.google.common.collect.Lists;
import com.rtf.framework.common.dto.EmptyDTOCallbackHandler;
import com.rtf.framework.common.dto.UtilDTO;
import com.rtf.framework.common.dto.params.AppBaseIdParam;
import com.rtf.framework.common.dto.params.AppBasePageParam;
import com.rtf.framework.common.dto.support.DTOCallbackHandler;
import com.rtf.framework.common.support.dao.entity.AppJpaIdEntity;
import com.rtf.framework.common.support.service.AppBaseDataService;
import com.rtf.framework.common.util.UtilReflection;
import com.rtf.framework.common.util.UtilTree;
import com.rtf.framework.web.http.AppIBaseController;
import com.rtf.framework.web.http.ResponseParam;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 应用接口功能适配器，将常用的前端restful接口的处理过程流程化和可配置化
 *
 * @param <T>
 * @param <ID>
 * @param <S>
 */
public abstract class AppFunQueryController<T extends AppJpaIdEntity, ID extends Long, S extends AppBaseDataService<T, ID>> extends AppIBaseController {

    /**
     * 获取泛型实体对象
     *
     * @return
     */
    protected Class<S> getEntityClass() {
        Class<S> entityClass = (Class<S>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return entityClass;
    }

    /**
     * 获取泛型服务处理
     *
     * @return
     */
    protected Class<S> getServiceClass() {
        Class<S> serviceClass = (Class<S>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[2];
        return serviceClass;
    }

    /**
     * 获取业务处理服务类
     *
     * @return
     */
    public S getTargetService() {
        S targetService = applicationContext.getBean(getServiceClass());
        return targetService;
    }

    /**
     * 对查询的条件进行后续处理
     *
     * @return
     */
    public Map<String, Object> queryParamPostHandle(String sourceMethod, Map<String, Object> searchParams) {
        return searchParams;
    }

    /**
     * 获取允许返回的字段集合
     *
     * @return
     */
    public List<String> getQueryFields(String sourceMethod) {
        Set<String> entityFields = UtilReflection.getAllFieldNames(getEntityClass());
        return Lists.newArrayList(entityFields);
    }

    /**
     * 获取对查询结果的扩展处理类
     *
     * @return
     */
    public DTOCallbackHandler getQueryCallbackHandler(String sourceMethod) {
        return new EmptyDTOCallbackHandler();
    }

    /**
     * 获取详情数据。
     */
    @PostMapping("/get")
    public ResponseParam get(@RequestBody AppBaseIdParam baseIdParam) {
        // 1.1 查询目标对象
        T targetEntity = getTargetService().get((ID) baseIdParam.getId());

        //1.2 将实体转换为数据传输对象
        List<String> queryFields = getQueryFields("get");
        DTOCallbackHandler dtoCallbackHandler = getDTOCallbackHandlerProxy(getQueryCallbackHandler("get"), true);

        //1.3 执行dto转换处理
        Map<String, Object> dtoObject = UtilDTO.toDTO(targetEntity, queryFields, dtoCallbackHandler);

        return ResponseParam.success()
                .data(dtoObject);
    }

    /**
     * 构建查询的排序条件，默认不排序
     *
     * @param searchParam
     * @return
     */
    public String[] buildQueryOrder(Map<String, Object> searchParam) {
        return new String[]{"id_desc"};
    }

    /**
     * 执行分页查询
     *
     * @param searchParam
     * @param pageNum
     * @param pageSize
     * @param queryOrder
     * @return
     */
    public Page doQueryByPage(Map<String, Object> searchParam, int pageNum, int pageSize, String[] queryOrder) {
        return getTargetService().queryByPage(searchParam, pageNum, pageSize, queryOrder);
    }

    /**
     * 用户记录分页查询
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/queryByPage")
    public ResponseParam queryByPage(@RequestBody Map<String, Object> searchParam) throws Exception {
        //1.1 对查询参数进行格式化处理
        searchParam = queryParamPostHandle("queryByPage", searchParam);

        //1.2 构建查询参数
        AppBasePageParam pageParam = buildPageParam("queryByPage", searchParam);

        //1.3 构建排序条件
        String[] queryOrder = buildQueryOrder(searchParam);

        //2.1 分页查询
        Page targetPage = doQueryByPage(searchParam, pageParam.getPageNum(), pageParam.getPageSize(), queryOrder);

        //2.2 对分页查询的结果进行格式化
        List<String> queryFields = getQueryFields("queryByPage");
        DTOCallbackHandler dtoCallbackHandler = getDTOCallbackHandlerProxy(getQueryCallbackHandler("queryByPage"), true);

        List<Map<String, Object>> targetDtoList = UtilDTO.toDTO(targetPage.getContent(), queryFields, dtoCallbackHandler);

        //3.1 返回分页查询结果
        return ResponseParam.success()
                .pageParam(targetPage)
                .datalist(targetDtoList);
    }

    /**
     * 列表查询的后续处理，只针对列表进行处理
     *
     * @param targetDtoList
     * @return
     */
    public List<Map<String, Object>> queryListPostHandle(List<Map<String, Object>> targetDtoList) {
        // 对返回的结果是否转换为树的处理
        AppTreeConfig treeConfig = queryListTreeConfig();
        if (treeConfig != null && treeConfig.isEnable()) {
            targetDtoList = UtilTree.getTreeData(targetDtoList, treeConfig.getIdField(), treeConfig.getParentIdField(),
                    treeConfig.getChildrenKey(), treeConfig.isRemoveIdField());
        }

        return targetDtoList;
    }

    /**
     * 查询结果的树配置，默认不转换为树
     *
     * @return
     */
    public AppTreeConfig queryListTreeConfig() {
        return new AppTreeConfig();
    }

    /**
     * 应用分类查询全部
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/list")
    public ResponseParam queryList(@RequestBody Map<String, Object> searchParam) {
        //1.1 对查询参数进行格式化处理
        searchParam = queryParamPostHandle("queryList", searchParam);

        //1.2 构建排序条件
        String[] queryOrder = buildQueryOrder(searchParam);

        //2.1 执行查询
        List<T> targetList = doQueryByList(searchParam, queryOrder);

        //3.2 对查询的结果进行格式化
        List<String> queryFields = getQueryFields("queryList");
        DTOCallbackHandler dtoCallbackHandler = getDTOCallbackHandlerProxy(getQueryCallbackHandler("queryList"), true);

        List<Map<String, Object>> targetDtoList = UtilDTO.toDTO(targetList, queryFields, dtoCallbackHandler);

        //4.1 对列表进行返回前的最后处理
        targetDtoList = queryListPostHandle(targetDtoList);

        return ResponseParam.success()
                .datalist(targetDtoList);
    }

    /**
     * 执行列表查询
     *
     * @param searchParam
     * @param queryOrder
     * @return
     */
    public List<T> doQueryByList(Map<String, Object> searchParam, String[] queryOrder) {
        return getTargetService().queryAll(searchParam, queryOrder) ;
    }

}
